package com.korion.srceencapture

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.PixelFormat
import android.graphics.Rect
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.ImageReader
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Bundle
import android.os.SystemClock
import android.util.Log
import android.view.PixelCopy
import android.view.View
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.nio.Buffer
import java.nio.ByteBuffer
import java.text.SimpleDateFormat

class MainActivity : AppCompatActivity(), View.OnClickListener {

    private lateinit var bitmapHandler: BitmapHandler

    private lateinit var playViewWrap: PlayViewWrap

    private val TAG = "MainActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        tv_time.post(object : Runnable {
            val format = SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
            override fun run() {
                if (!isFinishing) {
                    val time = System.currentTimeMillis()
                    tv_time.text = format.format(time)
                    tv_time.postDelayed(this, 1)
                }
            }
        })

        btn_0.setOnClickListener(this)
        btn_1.setOnClickListener(this)
        btn_2.setOnClickListener(this)
        btn_3.setOnClickListener(this)

        playViewWrap = PlayViewWrap(surface_view)
        bitmapHandler = BitmapHandler.inst()
        bitmapHandler.init(this)
    }


    override fun onClick(v: View) {
        when (v.id) {
            R.id.btn_0 -> {
                captureWindowByDraw()
            }
            R.id.btn_1 -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    captureWindowByPixelCopy()
                }
            }
            R.id.btn_2 -> {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    captureWindowByPixelCopy2(true)
                } else {
                    val width = window.decorView.width
                    val height = window.decorView.height
                    CommandExec.screenShot(this, width, height)
//                    val bitmap = SurfaceControlProxy.screenshot(width, height)
//                    val name = tv_time.text.toString().replace(" ", "_")
//                    bitmapHandler.postSaveBitmap(bitmap, name)
                }
            }
            R.id.btn_3 -> {
                captureWindowByMediaProject()
            }
        }
    }

    private fun captureWindowByDraw(){
        val view = window.decorView
        val bitmap =
            Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        view.draw(canvas)
        val name = tv_time.text.toString().replace(" ", "_")
        bitmapHandler.postSaveBitmap(bitmap, "$name.jpg")
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun captureWindowByPixelCopy(){
        val view = window.decorView
        val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
        val locationOfViewInWindow = intArrayOf(0, 0)
        view.getLocationInWindow(locationOfViewInWindow)

        PixelCopy.request(window, bitmap, { copyResult ->
            if (copyResult == PixelCopy.SUCCESS) {
                val name = tv_time.text.toString().replace(" ", "_")
                bitmapHandler.postSaveBitmap(bitmap, "$name.jpg")
            } else {
                Log.e(TAG, "Pixel copy fail.")
            }
        }, bitmapHandler.handler)
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun captureWindowByPixelCopy2(merge2: Boolean){
        val name = tv_time.text.toString().replace(" ", "_")
        val surfaceBitmap = Bitmap.createBitmap(
            surface_view.width,
            surface_view.height,
            Bitmap.Config.ARGB_8888
        )
        PixelCopy.request(surface_view, surfaceBitmap, { copyResult ->
            if (copyResult == PixelCopy.SUCCESS) {
//                bitmapHandler.postSaveBitmap(surfaceBitmap, "$name.jpg")
                val view = window.decorView
                val locationOfViewInWindow = intArrayOf(0, 0)
                surface_view.getLocationInWindow(locationOfViewInWindow)

                val bgBitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
                PixelCopy.request(window, bgBitmap, {
                    if (copyResult == PixelCopy.SUCCESS) {
                        val x = locationOfViewInWindow[0]
                        val y = locationOfViewInWindow[1]
                        val result = if (merge2) {
                            mergeBitmap2(bgBitmap, surfaceBitmap, Rect(x, y,
                                x + surfaceBitmap.width,
                                y + surfaceBitmap.height
                            )
                        )} else {
                            mergeBitmap(bgBitmap, surfaceBitmap, Rect(x, y,
                                x + surfaceBitmap.width,
                                y + surfaceBitmap.height
                            ))
                        }
                        bitmapHandler.postSaveBitmap(result, "$name.jpg")
                    } else {
                        Log.e(TAG, "Pixel copy fail.")
                    }
                }, bitmapHandler.handler)
            } else {
                Log.e(TAG, "Pixel copy fail.")
            }
        }, bitmapHandler.handler)
    }

    private fun mergeBitmap(
        bgBitmap: Bitmap,
        surfaceBitmap: Bitmap,
        rect: Rect
    ): Bitmap {
        val start = System.currentTimeMillis()
        val bitmap: Bitmap = bgBitmap.copy(Bitmap.Config.ARGB_8888, true)
        val canvas = Canvas(bitmap)
//        val surfaceRect = Rect(0, 0, surfaceBitmap.width, surfaceBitmap.height)
        canvas.drawBitmap(surfaceBitmap, null, rect, null)
        Log.d(TAG, "mergeBitmap1: merge cost:${System.currentTimeMillis() - start}")
        return bitmap
    }

    private fun mergeBitmap2(bgBitmap: Bitmap,
                             surfaceBitmap: Bitmap,
                             rect: Rect): Bitmap{
        val start = System.currentTimeMillis()
        val pixels = IntArray(surfaceBitmap.width * surfaceBitmap.height)
        surfaceBitmap.getPixels(pixels, 0, surfaceBitmap.width, 0, 0, surfaceBitmap.width, surfaceBitmap.height)
        bgBitmap.setPixels(pixels, 0, surfaceBitmap.width, rect.left, rect.top, surfaceBitmap.width, surfaceBitmap.height)
        Log.d(TAG, "mergeBitmap2: merge cost:${System.currentTimeMillis() - start}")
        return bgBitmap
    }


    private var mMediaProjectionManager: MediaProjectionManager? = null
    private var mediaProjection: MediaProjection? = null
    private var virtualDisplay: VirtualDisplay? = null
    private fun captureWindowByMediaProject(){
        mMediaProjectionManager = application.getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
        val intent = mMediaProjectionManager?.createScreenCaptureIntent()
        startActivityForResult(intent, 0)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == 0 && resultCode == RESULT_OK && data != null) {
            mediaProjection = mMediaProjectionManager?.getMediaProjection(resultCode, data)
            readImage()
            return
        }
        super.onActivityResult(requestCode, resultCode, data)
    }

    private fun readImage() {
        val width = window.decorView.width
        val height = window.decorView.height
        val dpi = resources.displayMetrics.densityDpi
        val imageReader = ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, 1)
        imageReader.setOnImageAvailableListener({
            val image = it.acquireLatestImage()
            val name = tv_time.text.toString().replace(" ", "_")
            bitmapHandler.postSaveImage(image, "$name.jpg")
            virtualDisplay?.release()
            imageReader.setOnImageAvailableListener(null, bitmapHandler.handler)
        }, bitmapHandler.handler)
        virtualDisplay = mediaProjection?.createVirtualDisplay("ScreenShot",
            width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, imageReader.surface, object :
            VirtualDisplay.Callback() {
                override fun onPaused() {
                    Log.d("CYY", "onPaused")
                }

                override fun onResumed() {
                    Log.d("CYY", "onResumed")
                }

                override fun onStopped() {
                    Log.d("CYY", "onStopped")
                }
            }, bitmapHandler.handler)
    }
}